package io.gitee.zhangbinhub.acp.cloud.server.helloworld.controller;

import io.gitee.zhangbinhub.acp.boot.exceptions.WebException;
import io.gitee.zhangbinhub.acp.boot.interfaces.LogAdapter;
import io.gitee.zhangbinhub.acp.boot.tools.IpTools;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.oauth2.server.resource.authentication.BearerTokenAuthentication;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * @author zhangbin by 2018-3-6 15:34
 * @since JDK 11
 */
@RestController
@RefreshScope
public class HelloWorldController {

    private final LogAdapter logAdapter;
    private final WebClient.Builder webClientBuilder;

    @Value("${acp.test.properties}")
    private String properties;

    @Autowired
    public HelloWorldController(LogAdapter logAdapter, @Qualifier(value = "customerWebClientTest") WebClient.Builder webClientBuilder) {
        this.logAdapter = logAdapter;
        this.webClientBuilder = webClientBuilder;
    }

    @PostMapping(value = "/helloworld", produces = MediaType.TEXT_PLAIN_VALUE)
    public Mono<String> helloWorld(@RequestHeader("Authorization") String authorization,
                                   @RequestBody String content) throws WebException {
        Mono<String> helloResponse = webClientBuilder.baseUrl("http://atomic-hello").build()
                .get().uri(uriBuilder -> uriBuilder
                        .path("/hello")
                        .queryParam("name", content)
                        .build())
                .header(HttpHeaders.AUTHORIZATION, authorization)
                .retrieve()
                .bodyToMono(String.class)
                .doOnError(throwable -> logAdapter.error("HelloServer hystrix caused by: " + throwable.getMessage(), throwable))
                .onErrorReturn("Hello service Hystrix[" + content + "]");
        Mono<String> worldResponse = webClientBuilder.baseUrl("http://atomic-world").build()
                .get().uri(uriBuilder -> uriBuilder
                        .path("/world")
                        .queryParam("name", content)
                        .build())
                .header(HttpHeaders.AUTHORIZATION, authorization)
                .retrieve()
                .bodyToMono(String.class)
                .doOnError(throwable -> logAdapter.error("WorldServerHystrix hystrix caused by: " + throwable.getMessage(), throwable))
                .onErrorReturn("World service Hystrix[" + content + "]");
        return Mono.zip(helloResponse, worldResponse, (hello, world) -> {
            String response = hello + "; " + world + "; properties=" + properties;
            logAdapter.info(response);
            return response;
        });
    }

    @GetMapping(value = "/access", produces = MediaType.TEXT_PLAIN_VALUE)
    @PreAuthorize("hasAnyAuthority('ROLE_ADMIN1')")
    public Mono<String> access(ServerWebExchange exchange) {
        String ip = IpTools.getRemoteIP(exchange);
        return Mono.just(ip);
    }

    @GetMapping(value = "/open/ips", produces = MediaType.TEXT_PLAIN_VALUE)
    public Mono<String> ips(ServerWebExchange exchange) {
        String ip = IpTools.getRemoteIP(exchange);
        return Mono.just(ip);
    }

    @Operation(summary = "获取当前用户token信息", description = "根据当前登录的用户token值，返回详细信息")
    @GetMapping(value = "/token-info", produces = MediaType.APPLICATION_JSON_VALUE)
    public Mono<BearerTokenAuthentication> currToken(BearerTokenAuthentication bearerTokenAuthentication) {
        return Mono.just(bearerTokenAuthentication);
    }

}
